// $Id: PluginFinder.cs 64 2008-05-06 18:29:47Z nvivo $

using System;
using System.ComponentModel;
using System.Data;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Reflection;
using System.Text;

namespace DBLGen
{
    internal sealed class PluginFinder : MarshalByRefObject
    {
        public static PluginInfo[] Find()
        {
            string path = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);

            return Find(path);
        }

        public static PluginInfo[] Find(string basePath)
        {
            AppDomain ad = AppDomain.CreateDomain("PluginFinder");
            PluginFinder pf = (PluginFinder) ad.CreateInstanceFromAndUnwrap(Assembly.GetExecutingAssembly().Location, typeof(PluginFinder).FullName);

            PluginInfo[] piList = pf.FindPlugins(basePath);

            AppDomain.Unload(ad);

            return piList;
        }

        private PluginInfo[] FindPlugins(string basePath)
        {
            string[] fileNames = Directory.GetFiles(basePath, "*.dll", SearchOption.TopDirectoryOnly);
            List<PluginInfo> list = new List<PluginInfo>();

            Type pluginType = typeof(Plugin);

            foreach (string fileName in fileNames)
            {
                Assembly asm = null;

                try
                {
                    asm = Assembly.LoadFile(fileName);
                }
                catch
                {
                    continue;
                }

                foreach (Type t in asm.GetTypes())
                {
                    if (t.IsSubclassOf(pluginType) && !t.IsAbstract)
                    {
                        PluginInfo info;

                        try
                        {
                            info = new PluginInfo(t);
                        }
                        catch
                        {
                            continue;
                        }

                        if (info != null)
                            list.Add(info);
                            
                    }
                }
            }

            return list.ToArray();
        }

    }
}
